package com.youxin.admin.auth.service.Impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.youxin.admin.auth.domain.ManageMenu;
import com.youxin.admin.auth.domain.MenuSearch;
import com.youxin.admin.auth.domain.router.RouterMeta;
import com.youxin.admin.auth.domain.router.VueRouter;
import com.youxin.admin.auth.mapper.MenuMapper;
import com.youxin.admin.auth.model.Menu;
import com.youxin.admin.auth.service.ChatMenuService;
import com.youxin.base.TResult;
import com.youxin.exception.SystemException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class ChatMenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements ChatMenuService {


    @Override
    public List<Menu> selectList(QueryWrapper<Menu> wrapper) throws SystemException {
        return this.baseMapper.selectList(wrapper);
    }

    @Override
    public Menu selectById(Integer id) throws SystemException {
        return this.baseMapper.selectById(id);
    }



    @Override
    public List<Menu> getUserAuthorityMenuByUserId(int id) throws SystemException {
        return getUserAuthorityMenuByUserId(id);
    }

    @Override
    public List<Menu> getUserAuthoritySystemByUserId(int id) throws SystemException {
        return this.baseMapper.selectAuthorityMenuByUserId(id);
    }

    @Override
    public boolean insert(Menu menu) throws SystemException {
        return save(menu);
    }

    @Override
    public List<Menu> getAllAuthorityElement() {
        return this.baseMapper.selectAllAuthority();
    }

    @Override
    public List<Menu> getAuthorityMenuByUserId(Integer userId) {
        return this.baseMapper.selectAuthorityMenuByUserId(userId);
    }


    @Override
    public IPage<Menu> selectByPage(String name, Integer menuId, Integer pageNo, Integer pageSize, String type) throws SystemException {
        QueryWrapper<Menu> criteria = new QueryWrapper<>();
        criteria.eq("parent_id", menuId);
        criteria.eq("type", type);
        if (StringUtils.isNotBlank(name)) {
            criteria.like("name", name);
        }
        IPage<Menu> page = new Page<>(pageNo, pageSize);
        return this.baseMapper.selectPage(page, criteria);
    }

    @Override
    public List<Menu> getAuthorityMenuByMenuId(String userId, String menuId) throws SystemException {
        return this.baseMapper.getAuthorityMenuByMenuId(userId, menuId);
    }

    @Override
    public boolean insertMenu(Menu menu) throws SystemException {
        return save(menu);
    }

    @Override
    public List<Menu> getAuthorityMenuListByUserId(String userId) throws SystemException {
        return this.baseMapper.selectAuthorityMenuListByUserId(userId);
    }

    @Override
    public TResult<List<ManageMenu>> listTreeMenu(MenuSearch menuSearch) throws SystemException {
        LambdaQueryWrapper<Menu> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Menu::getType, "0");
        if (menuSearch.getParentId() != null) {
            wrapper.eq(Menu::getParentId, menuSearch.getParentId());
        }
        if (!org.springframework.util.StringUtils.isEmpty(menuSearch.getMenuName())) {
            wrapper.eq(Menu::getName, menuSearch.getMenuName());
        }
        List<Menu> list = this.baseMapper.selectList(wrapper);
        List<ManageMenu> menus = list.stream().
                map(item -> JSONObject.parseObject(JSONObject.toJSONString(item), ManageMenu.class))
                .collect(Collectors.toList());
        List<ManageMenu> trees = buildTree(menus);
        return TResult.success(trees);
    }

    @Override
    public TResult<Set<String>> getPermissionsByUserName(String userName) throws SystemException {
        return null;
    }

    @Override
    public TResult<List<VueRouter>> getRouterByUser(String userName) throws SystemException {
        List<Menu> menus = new ArrayList<>();
        menus = this.baseMapper.findMenusByUserName(userName);

        List<VueRouter> routers = menus.stream().map(menu -> {
            VueRouter route = new VueRouter();
            route.setId(menu.getId().toString());
            route.setParentId(menu.getParentId().toString());
            route.setIcon(menu.getIcon());
            route.setPath(menu.getPath());
            route.setComponent(menu.getComponent());
            route.setName(menu.getName());
            route.setMeta(new RouterMeta(menu.getTitle()));
            return route;
        }).collect(Collectors.toList());
        return TResult.success(routers);
    }

    @Override
    public List<Menu> getUserMenuByUserId(String userId, String menuId) throws SystemException {
        return this.baseMapper.getUserMenuByUserId(userId, menuId);
    }

    public static List<VueRouter> buildVueRouter(List<VueRouter> routes) {
        if (routes == null) {
            return null;
        }
        List<VueRouter> list = new ArrayList<>();
        VueRouter topRouter = new VueRouter();
        topRouter.setName("index");
        topRouter.setRedirect("/home");
        topRouter.setComponent("BasicLayout");
        topRouter.setIcon("home");
        topRouter.setPath("/");
        topRouter.setChildren(new ArrayList<>());
        topRouter.setMeta(new RouterMeta("首页"));
        list.add(topRouter);

        routes.forEach(route -> {
            Integer parentId = Integer.valueOf(route.getParentId());
            if (parentId == null || 0 == parentId) {
                topRouter.getChildren().add(route);
                return;
            }
            for (VueRouter parent : routes) {
                Integer id = Integer.valueOf(parent.getId());
                if (id != null && id.equals(parentId)) {
                    if (parent.getChildren() == null) {
                        parent.initChildren();
                    }
                    parent.getChildren().add(route);
                    parent.setHasChildren(true);
                    route.setHasParent(true);
                    parent.setHasParent(true);
                    return;
                }
            }
        });

        return list;
    }

    public static List<ManageMenu> buildTree(List<ManageMenu> list) {
        List<ManageMenu> topNodes = new ArrayList<>();
        list.forEach(node -> {
            Integer pid = node.getParentId();
            if (pid == null || -1 == pid) {
                topNodes.add(node);
                return;
            }
            for (ManageMenu n : list) {
                Integer id = n.getId();
                if (id != null && id.equals(pid)) {
                    if (n.getChildren() == null) {
                        n.setChildren(new ArrayList<>());
                    }
                    n.getChildren().add(node);
                    return;
                }
            }
            if (topNodes.isEmpty()) {
                topNodes.add(node);
            }
        });
        return topNodes;
    }
}
